package com.mifengkong.kotlincommon.recyclerview.refreshload.load

import android.animation.ObjectAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.mifengkong.kotlincommon.recyclerview.refreshload.refresh.DropDownRefreshRecyclerView

/**
 * Created by jack on 2018/6/20
 */
class PullUpLoadingRecyclerView : DropDownRefreshRecyclerView {

    // 上拉加载更多的辅助类
    private var mLoadCreator: LoadViewCreator? = null
    // 上拉加载更多头部的高度
    private var mLoadViewHeight = 0
    // 上拉加载更多的头部View
    private var mLoadView: View? = null
    // 手指按下的Y位置
    private var mFingerDownY: Int = 0
    // 当前是否正在拖动
    private var mCurrentDrag = false
    // 当前的状态
    private var mCurrentLoadStatus: Int = 0

    companion object {
        // 默认状态
        const val LOAD_STATUS_NORMAL = 1
        // 上拉加载更多状态
        const val LOAD_STATUS_PULL_DOWN_REFRESH = 2
        // 松开加载更多状态
        const val LOAD_STATUS_LOOSEN_LOADING = 3
        // 正在加载更多状态
        const val LOAD_STATUS_LOADING = 4
    }

    private var isHaveData: Boolean = false

    constructor(context: Context?) : this(context, null)
    constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle)

    // 先处理上拉加载更多，同时考虑加载列表的不同风格样式，确保这个项目还是下一个项目都能用
    // 所以我们不能直接添加View，需要利用辅助类
    fun addLoadViewCreator(loadCreator: LoadViewCreator) {
        if (null == mLoadCreator) {
            this.mLoadCreator = loadCreator
            addLoadView()
        }
    }

    override fun setAdapter(adapter: Adapter<ViewHolder>) {
        super.setAdapter(adapter)
        addLoadView()
    }

    /**
     * 添加底部加载更多View
     */
    private fun addLoadView() {
        val adapter = adapter
        if (adapter != null && null != mLoadCreator) {
            // 添加底部加载更多View
            val loadView = mLoadCreator?.getLoadView(context, this)
            if (loadView != null) {
                this.mLoadView = loadView
                isHaveData = true
                addFooterView(mLoadView!!)
            }
        }
    }

    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        when (ev?.action) {
            MotionEvent.ACTION_DOWN ->
                // 记录手指按下的位置 ,之所以写在dispatchTouchEvent那是因为如果我们处理了条目点击事件，
                // 那么就不会进入onTouchEvent里面，所以只能在这里获取
                mFingerDownY = ev.rawY.toInt()
            MotionEvent.ACTION_UP -> if (mCurrentDrag) {
                restoreLoadView()
            }
        }
        return super.dispatchTouchEvent(ev)
    }

    /**
     * 重置当前加载更多状态
     */
    private fun restoreLoadView() {
        if (null == mLoadView) {
            return
        }
        val currentBottomMargin = (mLoadView?.layoutParams as MarginLayoutParams).bottomMargin
        if (mCurrentLoadStatus == LOAD_STATUS_LOOSEN_LOADING) {
            mCurrentLoadStatus = LOAD_STATUS_LOADING
            if (mLoadCreator != null) {
                mLoadCreator?.onLoading()
            }
            mListener?.onLoad()
        }

        // 回弹到指定位置
        val animator = ObjectAnimator.ofFloat(currentBottomMargin.toFloat(), 0.0f).setDuration(currentBottomMargin.toLong())
        animator.addUpdateListener({ animation ->
            val currentTopMargin = animation.animatedValue as Float
            setLoadViewMarginBottom(currentTopMargin.toInt())
        })
        animator.start()
        mCurrentDrag = false
    }

    /**
     * 设置加载View的marginBottom
     */
    private fun setLoadViewMarginBottom(marginBottom: Int) {
        var bottomMargin = marginBottom
        if (null == mLoadView) {
            return
        }
        mLoadView?.let {
            val params = it.layoutParams as MarginLayoutParams
            if (bottomMargin < 0) {
                bottomMargin = 0
            }
            params.bottomMargin = bottomMargin
            it.layoutParams = params
        }
    }

    override fun onTouchEvent(e: MotionEvent?): Boolean {
        when (e?.action) {
            MotionEvent.ACTION_MOVE -> {
                if (!isHaveData) {
                    return super.onTouchEvent(e)
                }
                // 如果是在最底部才处理，否则不需要处理
                if (canScrollDown() || mCurrentLoadStatus == LOAD_STATUS_LOADING) {
                    // 如果没有到达最顶端，也就是说还可以向上滚动就什么都不处理
                    return super.onTouchEvent(e)
                }

                if (mLoadCreator != null) {
                    mLoadViewHeight = mLoadView?.measuredHeight ?: 0
                }
                // 解决上拉加载更多自动滚动问题
                if (mCurrentDrag) {
                    scrollToPosition(adapter.itemCount - 1)
                }

                // 获取手指触摸拖拽的距离
                val distanceY = ((e.rawY - mFingerDownY) * mDragIndex).toInt()
                // 如果是已经到达头部，并且不断的向下拉，那么不断的改变refreshView的marginTop的值
                if (distanceY < 0) {
                    setLoadViewMarginBottom(-distanceY)
                    updateLoadStatus(-distanceY)
                    mCurrentDrag = true
                    return true
                }
            }
        }
        return super.onTouchEvent(e)
    }

    /**
     * 更新加载的状态
     */
    private fun updateLoadStatus(distanceY: Int) {
        mCurrentLoadStatus = when {
            distanceY <= 0 -> LOAD_STATUS_NORMAL
            distanceY < mLoadViewHeight -> LOAD_STATUS_PULL_DOWN_REFRESH
            else -> LOAD_STATUS_LOOSEN_LOADING
        }

        if (mLoadCreator != null) {
            mLoadCreator?.onPull(distanceY, mLoadViewHeight, mCurrentLoadStatus)
        }
    }

    /**
     * @return Whether it is possible for the child view of this layout to
     * scroll up. Override this if the child view is a custom view.
     * 判断是不是滚动到了最顶部，这个是从SwipeRefreshLayout里面copy过来的源代码
     */
    private fun canScrollDown(): Boolean {
        return canScrollVertically(1)
    }

    override fun onRefreshing() {
        super.onRefreshing()
        onLoadMoreComplete()
    }

    fun isAddLoadMoreView(): Boolean {
        return mLoadCreator != null
    }

    fun removeLoadMore() {
        onLoadMoreComplete()
        if (mLoadCreator != null) {
            removeFooterView(mLoadView!!)
            this.mLoadView = null
            mLoadCreator = null
        }
    }

    fun setNoMoreData() {
        onLoadMoreComplete()
        isHaveData = false
        mLoadCreator?.onNoMoreData()
    }

    fun setHaveData(haveData: Boolean) {
        isHaveData = haveData
    }

    /**
     * 停止加载更多
     */
    fun onLoadMoreComplete() {
        mCurrentLoadStatus = LOAD_STATUS_NORMAL
        restoreLoadView()
        if (mLoadCreator != null) {
            mLoadCreator?.onStopLoad()
        }
    }

    // 处理加载更多回调监听
    private var mListener: OnLoadMoreListener? = null

    fun setOnLoadMoreListener(listener: OnLoadMoreListener) {
        this.mListener = listener
    }

    interface OnLoadMoreListener {
        fun onLoad()
    }

}